package cc.bookcloud.tool.ocr.common.parsetext;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cc.bookcloud.tool.ocr.common.parsetext.feature.InvoiceFeatureBatchFactory;
import cc.bookcloud.tool.ocr.common.parsetext.feature.OcrTextInvoicePartitionEntity;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Desc: ORC文本解析工厂
 * @Version: 2.0
 * @Author: John Goo
 * @Date: 2024/11/26 09:50
 **/
@Slf4j
public class OcrTextParseFactory {


    // 火车票基准长度
    public static final Integer V_TRAIN_BASE_SIZE = 17;


    public static OcrTextParseResult ocrTextRec(String jsonStr) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        JSONObject dataJson = checkInvoiceType(jsonStr);
        //解析结果
        OcrTextParseResult result = parseText(dataJson);
        return result;
    }


    public static OcrTextParseResult ocrTextRec2(String jsonStr) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        JSONObject dataJson = checkInvoiceType(jsonStr);

        // ocr text解析文本
        OcrTextParseResult result = parseText(dataJson);
        return result;
    }


    /**
     * @param jsonStr
     * @return JSONObject
     * @Desc：检测票据类型
     * @Author：John Goo
     * @Date：2024/11/28 9:35
     */
    public static JSONObject checkInvoiceType(String jsonStr) {
        JSONObject data = new JSONObject();
        JSONArray retArray = new JSONArray();
        data.put("ocrRet", retArray);
        // 类型
        data.put("type", "未知");

        // 票据特征描述
        /** ************* jsonStr解析处理 *******/
        JSONObject ocrData = JSON.parseObject(jsonStr);
        // 解析文本原始数组
        String arrayStr = ocrData.getString("ocrRet");
        JSONArray outArray = JSONArray.parseArray(arrayStr);
        if (outArray.size() > 0) {
            JSONArray array = outArray.getJSONArray(0);
            // 票据行业
            int total = array.size();

            // 初步分支
            // 火车票区间
            if (total >= (17 - 4) && total <= (17 + 4)) {
                InvoiceFeatureAbstract feature = new InvoiceFeatureTrainTicket();
                //data.put("ocrRet", array);
                for (int i = 0; i < array.size(); i++) {
                    JSONArray rowJson = array.getJSONArray(i);
                    JSONObject row = new JSONObject();
                    String text = (String) rowJson.getJSONArray(1).get(0);
                    row.put("idx_" + (i + 1), (i + 1));
                    row.put("points", rowJson.getJSONArray(0));
                    row.put("text", text);
                    retArray.add(row);
                    feature.score(i,text,array);
                }
                if(feature.totalScore > 60){
                    data.put("type", "火车票");
                }
                System.out.println("====================计算评分："+feature.totalScore);


            }
        }


        return data;
    }




    /**
     * @param data
     * @return JSONObject
     * @Desc：文件解析转换
     * @Author：John Goo
     * @Date：2024/11/26 9:53
     */
    public static OcrTextParseResult parseText(JSONObject data) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 解析工厂

        // 火车票实体对象
        TrainTicketParseEntity trainTicket = new TrainTicketParseEntity();

        // 获取页面元数据模板定义信息
        List<OcrTextElementUnit> metaList = trainTicket.elementTemplateList;

        // ************* jsonStr解析处理 ****************//
        //JSONObject data = JSON.parseObject(jsonStr, Feature.OrderedField);

        // 解析文本原始数组
        JSONArray array = data.getJSONArray("ocrRet");
        for (int i = 0; i < array.size(); i++) {
            // 当前位置
            int pos = i;
            JSONObject rowJson = array.getJSONObject(pos);
            String text = rowJson.getString("text");

            // 解析row text文本信息
            parseTextRow(metaList, trainTicket, text, pos, array);
        }
        //JSONObject result =
        OcrTextParseResult result = new OcrTextParseResult();
        // json对象
        result.setRetJson((JSONObject) JSONObject.toJSON(trainTicket));
        result.setRetArray(trainTicket.transferJsonArray());
        return result;

    }


    /**
     * @param array
     * @return JSONObject
     * @Desc：文件解析转换
     * @Author：John Goo
     * @Date：2024/11/26 9:53
     */
    private static void parse(JSONArray array,OcrTextParseAbstract textParse) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 解析工厂

        // 火车票实体对象
       // TrainTicketParseEntity trainTicket = new TrainTicketParseEntity();

        // 获取页面元数据模板定义信息
        List<OcrTextElementUnit> metaList = textParse.elementTemplateList;

        // ************* jsonStr解析处理 ****************//
        //JSONObject data = JSON.parseObject(jsonStr, Feature.OrderedField);

        // 解析文本原始数组
        //JSONArray array = array.getJSONArray("ocrRet");
        for (int i = 0; i < array.size(); i++) {
            // 当前位置
            int pos = i;
            JSONObject rowJson = array.getJSONObject(pos);
            String text = rowJson.getString("text");

            // 解析row text文本信息
            parseTextRow(metaList, textParse, text, pos, array);
        }
        //JSONObject result =
       // OcrTextParseResult result = new OcrTextParseResult();
        // json对象
       // result.setRetJson((JSONObject) JSONObject.toJSON(textParse));
       // result.setRetArray(trainTicket.transferJsonArray());
        //return result;

    }

    private static void parseTextRow(List<OcrTextElementUnit> metaList, OcrTextParseAbstract textParse, String text, Integer pos, JSONArray array) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class cls = textParse.getClass();
        // 版面元素模板值
        for (int j = 0; j < metaList.size(); j++) {
            OcrTextElementUnit elementUnit = metaList.get(j);

            // 动态执行对象属性方法
            Method method = cls.getMethod(elementUnit.getAttrName(), String.class, Integer.class, JSONArray.class);
            // 是否命中:true-命中；false-未命中
            Boolean flag = (Boolean) method.invoke(textParse, text, pos, array);

            if (flag) {
                // 相匹配则移除队列
                metaList.remove(j);
                // 命中退出循环
                break;
            }
        }
    }


    /**
     * @param jsonStr
     * @return OcrTextParseResult
     * @Desc：火车票多张（上下版式解析）
     * @Author：John Goo
     * @Date：2024/11/29 9:24
     */
    public static List<JSONObject> trainTicketMany(String jsonStr) {

        // 定义多张发票
        List<JSONObject> list = new ArrayList<>();

        // 票据特征描述
        /** ************* jsonStr解析处理 *******/
        JSONObject ocrData = JSON.parseObject(jsonStr);

        // 解析文本原始数组
        String arrayStr = ocrData.getString("ocrRet");
        JSONArray outArray = JSONArray.parseArray(arrayStr);
        if (outArray.size() > 0) {
            JSONArray array = outArray.getJSONArray(0);
            JSONObject data = new JSONObject();
            list.add(data);
            JSONArray retArray = new JSONArray();
            data.put("ocrRet", retArray);
            // 类型
            data.put("type", "未知");

            //data.put("ocrRet", array);
            for (int i = 0; i < array.size(); i++) {
                JSONArray rowJson = array.getJSONArray(i);

                String text = (String) rowJson.getJSONArray(1).get(0);

                // 判断是否结束标志 ***jzsoft***
                if (text.contains("***jzsoft***")) {
                    // 重新初始化
                    data = new JSONObject();
                    retArray = new JSONArray();
                    data.put("ocrRet", retArray);
                    // 类型
                    data.put("type", "未知");
                    list.add(data);
                } else {
                    JSONObject row = new JSONObject();
                    row.put("idx_" + (i + 1), (i + 1));
                    row.put("points", rowJson.getJSONArray(0));
                    row.put("text", text);
                    retArray.add(row);
                }
            }
        }

        // 返回结果值
        List<JSONObject> retList = new ArrayList();
        list.forEach(item -> {
            try {
                OcrTextParseResult result = parseText(item);
                retList.add(result.getRetJson());

            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });

        return retList;
    }




    /**
     * @Desc：ocr文本解析（单张）
    * @Author：John Goo
    * @Date：2024/12/2 17:46
    * @param jsonStr
    * @return JSONObject
    */
    public static OcrTextParseAbstract textParse(String jsonStr)  {
        // 初始化发票特征识别工厂及数据格式转换
        InvoiceFeatureFactory featureFactory = new InvoiceFeatureFactory();

        // type :类型，typeDesc：类型描述，ocrRet：数组数据
        JSONObject data = featureFactory.transferAndIdentifyType(jsonStr);
        String type = data.getString("type");
        JSONArray array = data.getJSONArray("ocrRet");
        if(type == null){
            throw new RuntimeException("发票未识别出类型");
        }
        OcrTextParseAbstract  ocrTextParse = switchTypeTextParse(type,array);
        return ocrTextParse;

    }

    /**
     * @Desc：ocr文本解析（多张）
     * @Author：John Goo
     * @Date：2024/12/9 10:46
     * @param jsonStr
     * @return JSONObject
     */
    public static List<OcrTextParseAbstract>  textBatchParse(String jsonStr)  {
        List<OcrTextParseAbstract> list = new ArrayList<>();
        // 批量特征解析工厂
        InvoiceFeatureBatchFactory featureBatchFactory = new InvoiceFeatureBatchFactory();
        List<OcrTextInvoicePartitionEntity> featureList = featureBatchFactory.parsePartition(jsonStr);
        // 分区解析发票
        for(OcrTextInvoicePartitionEntity partitionEntity : featureList){
            String type = partitionEntity.getType();
            JSONArray array = partitionEntity.getOcrRet();
            OcrTextParseAbstract  ocrTextParse = switchTypeTextParse(type,array);
            if(ocrTextParse != null){
                list.add(ocrTextParse);
            }

        }
        return list;

    }


    private static  OcrTextParseAbstract switchTypeTextParse(String type,JSONArray array){
        log.info("{} 发票解析操作=========>类型："+type+","+InvoiceTypeEnum.getTypeDesc(type));
        OcrTextParseAbstract textParseEntity= null;
        try {
            switch (type) {
                case "vat_special_invoice":
                    ;
                    break;//增值税专用发票（数电纸质专票）

                case "motor_vehicle_sale_invoice":
                    ;
                    break;//机动车销售统一发票

                case "vat_common_invoice":
                    ;
                    break;//增值税普通发票（数电纸质普票）

                case "vat_electronic_invoice":
                    ;
                    break;//增值税电子普通发票

                case "vat_roll_invoice":
                    ;
                    break;//增值税普通发票（卷票）

                case "vat_electronic_toll_invoice":
                    ;
                    break;//增值税电子普通发票（通行费）

                case "used_car_purchase_invoice":
                    ;
                    break;//二手车销售统一发票

                case "general_machine_invoice":
                    ;
                    break;//通用机打发票

                case "quota_invoice":
                    ;
                    break;//通用定额发票

                case "passenger_transport_invoice":
                    ;
                    break;//旅客运输普票

                case "highway_passenger_invoice":
                    ;
                    break;//公路客运发票

                case "shipping_invoice":
                    ;
                    break;//船运客票

                case "taxi_ticket":
                    ;
                    break;//出租车发票

                case "parking_invoice":
                    ;
                    break;//停车费发票

                case "vehicle_toll":
                    ;
                    break;//过路过桥费发票、汽车通行费

                case "air_transport":
                    ;
                    break;//行程单

                case "train_ticket":
                    textParseEntity = new TrainTicketParseEntity();
                    parse(array, textParseEntity);
                    break;//火车票
                case "vat_invoice_sales_list":
                    ;
                    break;//增值税销货清单

                case "shop_receipt":
                    ;
                    break;//商户小票

                case "vat_electronic_special_invoice":
                    ;
                    break;//增值税电子专用发票

                case "vat_electronic_special_invoice_new":
                    ;
                    break;//全电电子发票(增值税专用发票)

                case "vat_electronic_invoice_new":
                    log.info("================ 正在开发中 【全电电子发票(普通发票)】 =========================");
                    textParseEntity = new PtElectronicInvoiceNormalParseEntity();
                    parse(array, textParseEntity);
                    break;//全电电子发票(普通发票)
                case "blockchain_electronic_invoice":
                    ;
                    break;//区块链电子发票

            }
        }catch (Exception e){
            log.error("【ocr text文本解析发生了异常】"+e);
        }
        return textParseEntity;
    }


}
